package com.yokead.common;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.jiangzeyin.Md5Util;
import cn.jiangzeyin.StringUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import com.qiniu.common.QiniuException;
import com.qiniu.common.Zone;
import com.qiniu.http.Response;
import com.qiniu.storage.BucketManager;
import com.qiniu.storage.Configuration;
import com.qiniu.storage.UploadManager;
import com.qiniu.storage.model.DefaultPutRet;
import com.qiniu.storage.model.FileInfo;
import com.qiniu.util.Auth;
import com.yokead.controller.images.ImagesControl;
import com.yokead.system.log.LogType;
import com.yokead.system.log.SystemLog;
import net.coobird.thumbnailator.Thumbnails;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.util.UUID;

/**
 * 七牛云
 * Created by jiangzeyin on 2017/7/11.
 */
public class QiNiuFile {

    /**
     * @param fileName 文件名
     * @param quality  100.0F 不压缩
     * @return 路径
     * @throws Exception e
     */
    public static String doUploadFile(String fileName, float quality) throws Exception {
        fileName = StringUtil.clearPath(fileName);
        // 获取文件md5
        String md5;
        try {
            md5 = Md5Util.getFile(new File(fileName));
            if (md5 == null) {
                throw new RuntimeException("获取文件md5为空");
            }
        } catch (NoSuchAlgorithmException | IOException e) {
            SystemLog.ERROR().error("获取异常", e);
            throw new RuntimeException("获取文件md5失败");
        }
        boolean urlFlag;
        try {
            urlFlag = urlExists(md5);
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException("获取文件在线信息失败");
        }
        if (urlFlag) {
            return md5;
        }
        // 图片文件处理
        FileInputStream fileInputStream = new FileInputStream(fileName);
        if (ImagesControl.isImage(fileInputStream)) {
            return doImage(fileName, quality);
        }
        // gif 判断
        String type = ImagesControl.getImageType(new File(fileName));
        if ("gif".equalsIgnoreCase(type)) {
            return doImage(fileName, quality);
        }
        if ("webp".equalsIgnoreCase(type)) {
            return doImage(fileName, quality);
        }
        // 普通文件判断
        if (!isTextFile(fileName)) {
            throw new RuntimeException("上传文件仅支持普通文件：" + fileName);
        }
        // 文件处理
        try {
            boolean uFlag = upload(fileName, md5);
            if (!uFlag) {
                throw new RuntimeException("上传文件败:-5");
            }
        } catch (IOException e) {
            SystemLog.ERROR().error("上传", e);
            throw new RuntimeException("上传文件失败:-6");
        }
        return md5;

    }

    /**
     * 处理图片上传
     *
     * @param fileName 文件路径
     * @param quality  压缩率
     * @return 上传结果
     * @throws FileNotFoundException e
     */
    private static String doImage(String fileName, float quality) throws FileNotFoundException {
        File imageFile = new File(fileName);
        String type = ImagesControl.getImageType(imageFile);
        if (type == null) {
            throw new RuntimeException("图片类型错误");
        }
        if (type.startsWith("error:jpg")) {
            SystemLog.LOG().info(fileName + " : 类型异常:" + type);
            type = "jpg";
        }
        if ("gif".equalsIgnoreCase(type)) {
            //   不压缩
        } else if ("webp".equalsIgnoreCase(type)) {
            // 不压缩
        } else if (quality != 100.0F) {
            // 压缩普通图片
            fileName = String.format("%s/%s.jpg", imageFile.getParent(), UUID.randomUUID());
            SystemLog.LOG().info("压缩图片：" + imageFile.getPath() + "  " + fileName);
            try {
                Thumbnails.of(imageFile).scale(1f).outputQuality(quality).toFile(new File(fileName));
            } catch (IOException e) {
                SystemLog.ERROR().error("压缩图片", e);
                throw new RuntimeException("压缩图片失败");
            }
        }
        // 二次图片获取md5
        String md5;
        try {
            md5 = Md5Util.getFile(new File(fileName));
            if (md5 == null) {
                throw new RuntimeException("获取图片文件md5为空");
            }
        } catch (NoSuchAlgorithmException | IOException e) {
            SystemLog.ERROR().error("获取md5", e);
            throw new RuntimeException("获取图片文件md5失败");
        }
        boolean urlFlag;
        // 二次图片信息判断是否存在
        try {
            urlFlag = urlExists(md5);
        } catch (IOException e) {
            SystemLog.ERROR().error("判断错误", e);
            throw new RuntimeException("获取文件网上信息失败");
        }
        if (urlFlag) {
            return md5;
        }
        // 上传图片文件
        try {
            boolean uFlag = upload(fileName, md5);
            if (!uFlag) {
                throw new RuntimeException("上传图片文件败:-5");
            }
        } catch (IOException e) {
            SystemLog.ERROR().error("上传", e);
            throw new RuntimeException("上传图片文件失败:-6");
        }
        return md5;
    }

    /**
     * 判断空间中是否存在对应文件
     *
     * @param keyName
     * @return
     * @throws IOException
     */
    private static boolean urlExists(String keyName) throws IOException {
        //构造一个带指定Zone对象的配置类
        Configuration cfg = new Configuration(Zone.autoZone());
        //...其他参数参考类注释
        // UploadManager uploadManager = new UploadManager(cfg);
        //...生成上传凭证，然后准备上传

        String bucket = QiNiuUtil.getImagesBucket();
        //Auth auth = QiNiuConfig.createAuth();
        Auth auth = QiNiuUtil.getAuth();
        BucketManager bucketManager = new BucketManager(auth, cfg);
        try {
            FileInfo fileInfo = bucketManager.stat(bucket, keyName);
            return fileInfo != null;
        } catch (QiniuException ex) {
            if (ex.code() != 612) {
                throw ex;
            }
            return false;
        }
    }

    public static String doUploadFile(String fileName) throws Exception {
        return doUploadFile(fileName, 100.0F);
    }

    public static boolean isTextFile(String filePath) throws IOException {
        try (FileInputStream fileInputStream = new FileInputStream(filePath)) {
            byte[] byteData = new byte[1];
            while (fileInputStream.read(byteData) > 0) {
                if (byteData[0] == 0) {
                    return false;
                }
            }
            return true;
        }
    }

    /**
     * 上传图片到空间中
     *
     * @param localFilePath
     * @param key
     * @return
     * @throws IOException
     */
    public static boolean upload(String localFilePath, String key) throws IOException {

        //构造一个带指定Zone对象的配置类
        Configuration cfg = new Configuration(Zone.autoZone());
        //...其他参数参考类注释
        UploadManager uploadManager = new UploadManager(cfg);
        //...生成上传凭证，然后准备上传
        String bucket = QiNiuUtil.getImagesBucket();
        //如果是Windows情况下，格式是 D:\\qiniu\\test.png
        //String localFilePath = "/home/qiniu/test.png";
        //默认不指定key的情况下，以文件内容的hash值作为文件名
        //String key = null;
        Auth auth = QiNiuUtil.getAuth();
        String upToken = auth.uploadToken(bucket);
        try {
            Response response = uploadManager.put(localFilePath, key, upToken);
            //解析上传成功的结果
            DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
            SystemLog.LOG().info("上传成功" + putRet.key + "  " + putRet.hash);
            return true;
        } catch (QiniuException ex) {
            SystemLog.LOG(LogType.CONTROL_ERROR).error("上传异常", ex);
            return false;
        }
    }


    public static BucketManager createImages() throws IOException {
        File file = Config.QiNiu.getQiNiuConfigFile();
        String json = FileUtil.readString(file, CharsetUtil.CHARSET_UTF_8);
        JSONObject jsonObject = JSON.parseObject(json);
        JSONObject images = jsonObject.getJSONObject("images");
        //构造一个带指定Zone对象的配置类
        Configuration cfg = new Configuration(Zone.autoZone());
        //...其他参数参考类注释
        String accessKey = images.getString("ak");
        String secretKey = images.getString("sk");
        Auth auth = Auth.create(accessKey, secretKey);
        return new BucketManager(auth, cfg);
    }

    public static void main(String[] a) throws FileNotFoundException {
        System.out.println(ImagesControl.getImageType(new File("/etc/nginx/boot/temp/img/admin/F38C78864FF8369C99296D6B79B14F66")));

    }
}
